﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using JavaSubstitutes;

namespace Sprites
{
	public class Fireball: Sprite
	{
		private static double GROUND_INERTIA = 0.89f;
		private static double AIR_INERTIA = 0.89f;

		private double runTime;
		private bool onGround = false;

		protected int width = 4;
		public int height = 24;

		private LevelScene world;
		public int facing;

		public bool avoidCliffs = false;
		public int anim;

		public bool dead = false;
		private int deadTime = 0;

		public Fireball(LevelScene world, double x, double y, int facing)
		{
			sheet = Art.particles;

			this.x = x;
			this.y = y;
			this.world = world;
			xPicO = 4;
			yPicO = 4;

			yPic = 3;
			height = 8;
			this.facing = facing;
			wPic = 8;
			hPic = 8;

			xPic = 4;
			yDelta = 4;
		}

		public override void move()
		{
			if (deadTime > 0)
			{
				for (int i = 0; i < 8; i++)
				{
					world.addSprite(new Sparkle((int)(x + RandomExtensions.random() * 8 - 4) + 4, (int)(y + RandomExtensions.random() * 8 - 4) + 2, (double)RandomExtensions.random() * 2 - 1 - facing, (double)RandomExtensions.random() * 2 - 1, 0, 1, 5));
				}
				spriteContext.removeSprite(this);

				return;
			}

			if (facing != 0) anim++;

			double sideWaysSpeed = 8f;
			//        double sideWaysSpeed = onGround ? 2.5f : 1.2f;

			if (xDelta > 2)
			{
				facing = 1;
			}
			if (xDelta < -2)
			{
				facing = -1;
			}

			xDelta = facing * sideWaysSpeed;

			world.checkFireballCollide(this);

			xFlipPic = facing == -1;

			runTime += (Math.Abs(xDelta)) + 5;

			xPic = (anim) % 4;



			if (!move(xDelta, 0))
			{
				die();
			}

			onGround = false;
			move(0, yDelta);
			if (onGround) yDelta = -10;

			yDelta *= 0.95f;
			if (onGround)
			{
				xDelta *= GROUND_INERTIA;
			}
			else
			{
				xDelta *= AIR_INERTIA;
			}

			if (!onGround)
			{
				yDelta += 1.5f;
			}
		}

		private bool move(double xa, double ya)
		{
			while (xa > 8)
			{
				if (!move(8, 0)) return false;
				xa -= 8;
			}
			while (xa < -8)
			{
				if (!move(-8, 0)) return false;
				xa += 8;
			}
			while (ya > 8)
			{
				if (!move(0, 8)) return false;
				ya -= 8;
			}
			while (ya < -8)
			{
				if (!move(0, -8)) return false;
				ya += 8;
			}

			bool collide = false;
			if (ya > 0)
			{
				if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
				else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
				else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
				else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
			}
			if (ya < 0)
			{
				if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
				else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
				else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
			}
			if (xa > 0)
			{
				if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
				if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
				if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;

				if (avoidCliffs && onGround && !world.level.isBlocking((int)((x + xa + width) / 16), (int)((y) / 16 + 1), xa, 1)) collide = true;
			}
			if (xa < 0)
			{
				if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
				if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
				if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;

				if (avoidCliffs && onGround && !world.level.isBlocking((int)((x + xa - width) / 16), (int)((y) / 16 + 1), xa, 1)) collide = true;
			}

			if (collide)
			{
				if (xa < 0)
				{
					x = (int)((x - width) / 16) * 16 + width;
					this.xDelta = 0;
				}
				if (xa > 0)
				{
					x = (int)((x + width) / 16 + 1) * 16 - width - 1;
					this.xDelta = 0;
				}
				if (ya < 0)
				{
					y = (int)((y - height) / 16) * 16 + height;
					this.yDelta = 0;
				}
				if (ya > 0)
				{
					y = (int)(y / 16 + 1) * 16 - 1;
					onGround = true;
				}
				return false;
			}
			else
			{
				x += xa;
				y += ya;
				return true;
			}
		}

		private bool isBlocking(double _x, double _y, double xa, double ya)
		{
			int x = (int)(_x / 16);
			int y = (int)(_y / 16);
			if (x == (int)(this.x / 16) && y == (int)(this.y / 16)) return false;

			bool blocking = world.level.isBlocking(x, y, xa, ya);

			byte block = world.level.getBlock(x, y);

			return blocking;
		}

		public void die()
		{
			dead = true;

			xDelta = -facing * 2;
			yDelta = -5;
			deadTime = 100;
		}
	}
}